package linear;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;

import sgd.LR;

public class LTools {
	
	public static String trainFilePath = "/Users/macpro724/Desktop/BigML/proj/track2/training.txt";
	public static NumberFormat formatter = new DecimalFormat("#0.000000");
	
	public static LFeature getLFeature(){
		LFeature l = new LFeature();
		try{
			BufferedReader br = new BufferedReader(new FileReader(trainFilePath));
			String line;
			int lineNum = 0;
			double sumI = 0;
			while ((line = br.readLine()) != null){
				if (lineNum % 1000000 == 0)
					System.out.println(lineNum);
				lineNum++;
				String[] paras = line.split("\t");// id seg1|seg2|seg3....
				int click = Integer.parseInt(paras[0]);
				int impression = Integer.parseInt(paras[1]);
				
				sumI += impression;
				
				int adID = Integer.parseInt(paras[3]);
				int aderID = Integer.parseInt(paras[4]);
				int queryID = Integer.parseInt(paras[7]);
				int purchaseID = Integer.parseInt(paras[8]);
				int titleID = Integer.parseInt(paras[9]);
				int descriptionID = Integer.parseInt(paras[10]);
				int userID = Integer.parseInt(paras[11]);
				int posID = Integer.parseInt(paras[6]);
				
				String userinfo = UserProfile.getInstance().getMap().get(userID);
				if (userinfo != null){
					String[] segs = userinfo.split("\\|");
					int genderID = Integer.parseInt(segs[0]);
					int ageID = Integer.parseInt(segs[1]);
					updateMap(l.clickinfo.get(l.getMapIndex("sex")), genderID, click);
					updateMap(l.imprinfo.get(l.getMapIndex("sex")), genderID, impression);
					
					updateMap(l.clickinfo.get(l.getMapIndex("age")), ageID, click);
					updateMap(l.imprinfo.get(l.getMapIndex("age")), ageID, impression);
				}
				
				//update click
				updateMap(l.clickinfo.get(l.getMapIndex("ad")), adID, click);
				updateMap(l.clickinfo.get(l.getMapIndex("ader")), aderID, click);
				updateMap(l.clickinfo.get(l.getMapIndex("query")), queryID, click);
				updateMap(l.clickinfo.get(l.getMapIndex("pur")), purchaseID, click);
				updateMap(l.clickinfo.get(l.getMapIndex("title")), titleID, click);
				updateMap(l.clickinfo.get(l.getMapIndex("des")), descriptionID, click);
				updateMap(l.clickinfo.get(l.getMapIndex("user")), userID, click);
				updateMap(l.clickinfo.get(l.getMapIndex("pos")), posID, click);
				
				//update imp
				updateMap(l.imprinfo.get(l.getMapIndex("ad")), adID, impression);
				updateMap(l.imprinfo.get(l.getMapIndex("ader")), aderID, impression);
				updateMap(l.imprinfo.get(l.getMapIndex("query")), queryID, impression);
				updateMap(l.imprinfo.get(l.getMapIndex("pur")), purchaseID, impression);
				updateMap(l.imprinfo.get(l.getMapIndex("title")), titleID, impression);
				updateMap(l.imprinfo.get(l.getMapIndex("des")), descriptionID, impression);
				updateMap(l.imprinfo.get(l.getMapIndex("user")), userID, impression);
				updateMap(l.imprinfo.get(l.getMapIndex("pos")), posID, impression);
				
			}
			br.close();
			l.imean = sumI/lineNum;
		}catch(Exception e){
			e.printStackTrace();
		}
		return l;
	}
	
	public static void updateMap(HashMap<Integer, Integer> map, int id, int value){
		if (!map.containsKey(id)){
			map.put(id, value);
		}else{
			int oldvalue = map.get(id);
			map.put(id, oldvalue + value);
		}
	}
	
	public static void analyzeMean(LFeature l){
		System.out.println("Overall-Mean:" + l.imean);
		for (int i = 0; i < 10; i++){
			double sumImp = 0.0;
			HashMap<Integer, Integer> map = l.imprinfo.get(i);
			Iterator<Entry<Integer, Integer>> iter = map.entrySet().iterator();
			while(iter.hasNext()){
				Entry<Integer, Integer> entry = iter.next();
				sumImp += entry.getValue();
			}
			l.mean[i] = sumImp/map.size();
			System.out.println("Mean@Size: " + l.mean[i] + "\t" + map.size());
		}
	}
	
	public static void generateTrain(String trainfile, String[] output, LFeature l){
		try{
			BufferedReader br = new BufferedReader(new FileReader(trainfile));
			BufferedWriter[] bws = new BufferedWriter[output.length];
			for (int i = 0; i < bws.length; i++){
				bws[i] = new BufferedWriter(new FileWriter(output[i]));
			}
			String line;
			int lineNum = 0;
			while ((line = br.readLine()) != null){
				if (lineNum % 1000000 == 0)
					System.out.println(lineNum);
				lineNum++;
				String[] paras = line.split("\t");// id seg1|seg2|seg3....
				int click = Integer.parseInt(paras[0]);
				int impression = Integer.parseInt(paras[1]);
				
				int adID = Integer.parseInt(paras[3]);
				int aderID = Integer.parseInt(paras[4]);
				int queryID = Integer.parseInt(paras[7]);
				int purchaseID = Integer.parseInt(paras[8]);
				int titleID = Integer.parseInt(paras[9]);
				int descriptionID = Integer.parseInt(paras[10]);
				int userID = Integer.parseInt(paras[11]);
				
				//output y:
				bws[7].write(formatter.format(getBayesMean(click, impression, l.imean)));
				bws[7].write("\n");
				
				//output ad:
				if (l.clickinfo.get(0).containsKey(adID)){
					bws[0].write(formatter.format(getBayesMean(l.clickinfo.get(0).get(adID),
							l.imprinfo.get(0).get(adID), l.mean[0])));
				}else
					bws[0].write("0.034882");
				bws[0].write("\n");
				
				//output ader:
				if (l.clickinfo.get(1).containsKey(aderID)){
					bws[1].write(formatter.format(getBayesMean(l.clickinfo.get(1).get(aderID),
							l.imprinfo.get(1).get(aderID), l.mean[1])));
				}else
					bws[1].write("0.034882");
				bws[1].write("\n");
				
				//output query:
				if (l.clickinfo.get(2).containsKey(queryID)){
					bws[2].write(formatter.format(getBayesMean(l.clickinfo.get(2).get(queryID),
							l.imprinfo.get(2).get(queryID), l.mean[2])));
				}else
					bws[2].write("0.034882");
				bws[2].write("\n");
				
				//output purchase:
				if (l.clickinfo.get(3).containsKey(purchaseID)){
					bws[3].write(formatter.format(getBayesMean(l.clickinfo.get(3).get(purchaseID),
							l.imprinfo.get(3).get(purchaseID), l.mean[3])));
				}else
					bws[3].write("0.034882");
				bws[3].write("\n");
				
				//output title:
				if (l.clickinfo.get(4).containsKey(titleID)){
					bws[4].write(formatter.format(getBayesMean(l.clickinfo.get(4).get(titleID),
							l.imprinfo.get(4).get(titleID), l.mean[4])));
				}else
					bws[4].write("0.034882");
				bws[4].write("\n");
				
				//output des:
				if (l.clickinfo.get(5).containsKey(descriptionID)){
					bws[5].write(formatter.format(getBayesMean(l.clickinfo.get(5).get(descriptionID),
							l.imprinfo.get(5).get(descriptionID), l.mean[5])));
				}else
					bws[5].write("0.034882");
				bws[5].write("\n");
				
				//output user:
				if (l.clickinfo.get(6).containsKey(userID)){
					bws[6].write(formatter.format(getBayesMean(l.clickinfo.get(6).get(userID),
							l.imprinfo.get(6).get(userID), l.mean[6])));
				}else
					bws[6].write("0.034882");
				bws[6].write("\n");
			}
			
			br.close();
			for (int i = 0; i < bws.length; i++)
				bws[i].close();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public static void generateTrain2(String trainfile, String[] output, LFeature l){
		try{
			BufferedReader br = new BufferedReader(new FileReader(trainfile));
			BufferedWriter[] bws = new BufferedWriter[output.length];
			for (int i = 0; i < bws.length; i++){
				bws[i] = new BufferedWriter(new FileWriter(output[i]));
			}
			String line;
			int lineNum = 0;
			while ((line = br.readLine()) != null){
				if (lineNum % 1000000 == 0)
					System.out.println(lineNum);
				lineNum++;
				String[] paras = line.split("\t");// id seg1|seg2|seg3....
				
				int userID = Integer.parseInt(paras[11]);
				int posID = Integer.parseInt(paras[6]);
				
				//output user:
				if (l.clickinfo.get(7).containsKey(posID)){
					bws[0].write(formatter.format(getBayesMean(l.clickinfo.get(7).get(posID),
							l.imprinfo.get(7).get(posID), 0)));
				}else
					bws[0].write("0.034882");
				bws[0].write("\n");
				
				String userinfo = UserProfile.getInstance().getMap().get(userID);
				if (userinfo != null){
					String[] segs = userinfo.split("\\|");
					int genderID = Integer.parseInt(segs[0]);
					int ageID = Integer.parseInt(segs[1]);
					bws[1].write(formatter.format(getBayesMean(l.clickinfo.get(8).get(genderID),
							l.imprinfo.get(8).get(genderID), 0)));
					bws[1].write("\n");
					
					bws[2].write(formatter.format(getBayesMean(l.clickinfo.get(9).get(ageID),
							l.imprinfo.get(9).get(ageID), 0)));
					bws[2].write("\n");
				}else{
					bws[1].write("0.034882");
					bws[1].write("\n");
					bws[2].write("0.034882");
					bws[2].write("\n");
				}
			}
			
			br.close();
			for (int i = 0; i < bws.length; i++)
				bws[i].close();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public static double getBayesMean(int click, int impression, double mean){
		return ((1.0*click + mean*0.034882)/(mean + 1.0*impression));
	}
	
	public static void testLR(double[] w, LFeature l, String testPath, String resultPath, boolean[] b){
		try{
			System.out.println("lr begin test...");
			BufferedReader br = new BufferedReader(new FileReader(testPath));
			BufferedWriter bw = new BufferedWriter(new FileWriter(resultPath));
			String line;
			int index = 0;
			double[] f = new double[w.length];
			while ((line = br.readLine()) != null){
				if (index % 1000000 == 0)
					System.out.println(index);
				index++;
				String[] paras = line.split("\t");
				int adID = Integer.parseInt(paras[1]);
				int aderID = Integer.parseInt(paras[2]);
				int queryID = Integer.parseInt(paras[5]);
				int purchaseID = Integer.parseInt(paras[6]);
				int titleID = Integer.parseInt(paras[7]);
				int descriptionID = Integer.parseInt(paras[8]);
				int userID = Integer.parseInt(paras[9]);
				int posID = Integer.parseInt(paras[4]);
				
				//output ad:
				if (l.clickinfo.get(0).containsKey(adID)){
					f[0] = getBayesMean(l.clickinfo.get(0).get(adID),
							l.imprinfo.get(0).get(adID), l.mean[0]);
				}else
					f[0] = 0.034882;
				
				//output ader:
				if (l.clickinfo.get(1).containsKey(aderID)){
					f[1] = getBayesMean(l.clickinfo.get(1).get(aderID),
							l.imprinfo.get(1).get(aderID), l.mean[1]);
				}else
					f[1] = 0.034882;
				
				//output query:
				if (l.clickinfo.get(2).containsKey(queryID)){
					f[2] = getBayesMean(l.clickinfo.get(2).get(queryID),
							l.imprinfo.get(2).get(queryID), l.mean[2]);
				}else
					f[2] = 0.034882;
				
				//output purchase:
				if (l.clickinfo.get(3).containsKey(purchaseID)){
					f[3] = getBayesMean(l.clickinfo.get(3).get(purchaseID),
							l.imprinfo.get(3).get(purchaseID), l.mean[3]);
				}else
					f[3] = 0.034882;
				
				//output title:
				if (l.clickinfo.get(4).containsKey(titleID)){
					f[4] = getBayesMean(l.clickinfo.get(4).get(titleID),
							l.imprinfo.get(4).get(titleID), l.mean[4]);
				}else
					f[4] = 0.034882;
				
				//output des:
				if (l.clickinfo.get(5).containsKey(descriptionID)){
					f[5] = getBayesMean(l.clickinfo.get(5).get(descriptionID),
							l.imprinfo.get(5).get(descriptionID), l.mean[5]);
				}else
					f[5] = 0.034882;
				
				//output user:
				if (l.clickinfo.get(6).containsKey(userID)){
					f[6] = getBayesMean(l.clickinfo.get(6).get(userID),
							l.imprinfo.get(6).get(userID), l.mean[6]);
				}else
					f[6] = 0.034882;
				
				//output posID:
				if (l.clickinfo.get(7).containsKey(posID)){
					f[7] = getBayesMean(l.clickinfo.get(7).get(posID),
							l.imprinfo.get(7).get(posID), 0);
				}else
					f[7] = 0.034882;
				
				String userinfo = UserProfile.getInstance().getMap().get(userID);
				if (userinfo != null){
					String[] segs = userinfo.split("\\|");
					int genderID = Integer.parseInt(segs[0]);
					int ageID = Integer.parseInt(segs[1]);
					f[8] = getBayesMean(l.clickinfo.get(8).get(genderID),
							l.imprinfo.get(8).get(genderID), 0);
					f[9] = getBayesMean(l.clickinfo.get(9).get(ageID),
							l.imprinfo.get(9).get(ageID), 0);
				}else{
					f[8] = 0.034882;
					f[9] = 0.034882;
				}
				
				double y = 0;
				for (int i = 0; i < w.length; i++){
					if (b[i])
						y += f[i]*w[i];
				}
				
				bw.write(String.valueOf(y));
				bw.write("\n");
			}
			br.close();
			bw.flush();
			bw.close();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args){
//		LFeature l = getLFeature();
//		analyzeMean(l);
//		String[] outputs = {"_pos", "_gender", "_age"};
//		generateTrain2(trainFilePath, outputs, l);
//		LFeature.writeFeature(l, "lfeature");
//		String[] in = {"_ad","_ader", "_query", "_pur", "_title", 
//				"_des", "_user", "_pos", "_gender", "_age"};
//		String[] in = {"l_learn", "id_learn"};
//		String[] in = {"_query", "_title", "_user"};
//		LFeature l = LFeature.readFeature("lfeature");
//		double[] w = LR.trainLR("_y", in);
//		System.out.println("Feature:");
//		for (int i = 0; i < w.length; i++)
//			System.out.println(w[i]);
//		System.out.println("End Feature");
//		LR.outtrainLR("_y", in);
//		boolean[] b = {true, true, true, true, true, true, true, true};
//		testLR(w, l, "test", "output", b);
		
//		double[] w = {0.550920588662242,
//				0.08193362543591183};
		String[] in = {"lresult", "idresult"};
		LR.outtrainLR("idresult", in);
	}

}
